package com.hongying.consumer;

import com.hongying.constant.RabbitMqConstant;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
@RabbitListener(queues = RabbitMqConstant.DIRECT_QUEUE)
@Slf4j
public class DirectReceiver {

    @RabbitHandler
    public void process(String msg, Channel channel, Message message) throws IOException {
        try {
            log.info("小富收到消息：{}", msg);

            //TODO 具体业务

            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

            System.out.println("+++++++++++++++++++++++=");
            /**
             * waitForConfirmsOrDie批量消息确认：它会同时向服务器中确认之前当前通道中发送的所有的消息是否已经全部成功写入
             * 这个方法没有任何返回值，如果服务器中有一条消息没有发送成功，服务器不可访问，都会被认为消息发送失败
             * 需要进行消息的补发，可以设置超时时间，超过这个时间也会抛出异常InterruptedException，确认失败，等待补发消息
             * 注意：
             * 批量消息确认速度比普通消息确认要快
             * 但是一旦出现消息补发情况，不能确认是哪条消息没有发送成功，需要对所有消息进行补发
             * 批量在实战中使用频率高
             */
            channel.waitForConfirmsOrDie();
        }  catch (Exception e) {

            if (message.getMessageProperties().getRedelivered()) {

                log.error("消息已重复处理失败,拒绝再次接收...");

                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false); // 拒绝消息
            } else {

                log.error("消息即将再次返回队列处理...");

                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
            }
        }
    }


}
